package com.shujia.day08;


import java.util.Objects;

/*
    很重要：
        编写一个规范的自定义的数据对象类
            对于Mysql中一张表中的每一条数据实际上都可以看成一个对象的实例
            表的结构就相当于是一个Student类
        要求：
            1、有属性  属性是私有的
            2、通过get Set 函数对外提供属性的访问及修改
            3、重写构造函数 无参 有参
            4、重写toString方法

 */
class Student{
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void run(){
        System.out.println("学生需要锻炼..");
    }

    // show 方法是我们自己定义的，不规范 所以可以使用快捷方式来重写toString
//    public void show(){
//        System.out.println("name:"+name);
//        System.out.println("age:"+age);
//    }


    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

public class Code08Object {
    public static void main(String[] args) {
        /*
            Object类：
                这个类是所有类的父类 所有类直接或间接继承了该类
                Java为什么称为是一个面向对象的语言？
                    Object -> 对象
                    但是注意Java并不是一个完全面向对象的语言，因为 int short long 等基本数据类型 不是Object的子类

            Object类的成员方法
                public int hashCode()
                      判断两个对象是否相等，可以通过Hash值来进行判断
                public final Class getClass()
                       获取当前对象的类信息
                public String toString()
                        每次sout就是调用当前对象的toString方法，而该方法是继承于Object中的
                            一般情况下，需要对自定义类中的toString进行重写

                public boolean equals(Object obj)
                        表示判断某个对象是否等于另外一个对象，默认是通过 == 来判断其地址是否相等
                        子类在调用equal时，需要重写其父类的方法

                protected void finalize()
                protected Object clone()
         */

        // 获取Object类的对象
        Object obj1 = new Object();

        //  hashCode 表示是一个 哈希值 通过hash算法得到的结果
        //  哈希算法包含比较多 常见的 有 sha-256
        //      哈希算法的作用： 对于给定的一批数据，通过同样一个哈希函数 每次得到的结果都是一致的  存在有一个唯一的映射关系
        //

        System.out.println(obj1.hashCode());  // 1163157884
        System.out.println(obj1.hashCode());  // 1163157884

        Object obj2 = new Object();
        System.out.println(obj2.hashCode());  // 1956725890

        // 通过创建对象获取对应的方法，可以发现Object是Student的父类，并继承了父类中所有的成员方法
        Student student1 = new Student("周州",16);
        System.out.println(student1.hashCode());

        Class  studentClass = student1.getClass();
        System.out.println(studentClass);

        // toString
        System.out.println(student1); // sout 传入的对象，实际上就是调用其toString方法
//        System.out.println(student1.toString());  // ctrl + 鼠标左键 进入方法内
        //  return getClass().getName() + "@" + Integer.toHexString(hashCode());  打印结果是调用左边的逻辑获取的

        // toString 是Object提供的，那么打印一个自定义的类时，应该需要打印其属性信息
        //    如果要打印当前对象中的属性描述信息，那么需要重写当前自定义学生类中的toString方法
        System.out.println(student1.toString());

        String a = "String";
        String b = "String";

        Student student3 = new Student();
        Student student4 = new Student();

        System.out.println(a == b);  // a 和 b 指向的内存地址都是常量池中同一块位置，所以 == 比较其内存地址相等
        System.out.println(student3 == student4);  // 在堆中开辟了两块内容，分别存储了两个学生对象 所以内存地址不一样


        String hello1 = new String("hello");
        String hello2 = new String("hello");
        System.out.println(hello1);
        System.out.println(hello2);

        // 每次new 都会在堆中常量池外 开辟一个空间 所以两次比较地址结果不一致
        System.out.println(hello1 == hello2);


        // 创建两个属性相同的对象 进行比较时，要求结果为相同
        Student student5 = new Student("曹聪",18);
        Student student6 = new Student("曹聪",18);

        System.out.println("字符串："+hello1.equals(hello2));
        System.out.println("Student对象："+student5.equals(student6));

    }
}
